// Python language adapter implementation
use codegraph_core::{
    LanguageAdapter, Parser, SyntaxTree, CodeNode, CodeEdge, NodeType, EdgeType, Result,
    SourceLocation,
};
use codegraph_parser::TreeSitterParser;
use codegraph_graph::{GraphNode, GraphEdge};
use async_trait::async_trait;
use uuid::Uuid;
use std::collections::HashMap;

pub struct PythonAdapter {
    language_id: String,
    file_extensions: Vec<String>,
}

impl PythonAdapter {
    pub fn new() -> Self {
        Self {
            language_id: "python".to_string(),
            file_extensions: vec![".py".to_string(), ".pyw".to_string(), ".pyi".to_string()],
        }
    }
}

impl Default for PythonAdapter {
    fn default() -> Self {
        Self::new()
    }
}

#[async_trait]
impl LanguageAdapter for PythonAdapter {
    fn language_id(&self) -> &str {
        &self.language_id
    }

    fn file_extensions(&self) -> &[String] {
        &self.file_extensions
    }

    async fn create_parser(&self) -> Result<Box<dyn Parser>> {
        let parser = TreeSitterParser::python()?;
        Ok(Box::new(parser))
    }

    async fn extract_nodes(&self, tree: &dyn SyntaxTree) -> Result<Vec<Box<dyn CodeNode>>> {
        let mut nodes = Vec::new();
        let root = tree.root_node();

        // Extract different types of nodes
        self.extract_function_definitions(root.as_ref(), tree, &mut nodes).await?;
        self.extract_class_definitions(root.as_ref(), tree, &mut nodes).await?;
        self.extract_variable_assignments(root.as_ref(), tree, &mut nodes).await?;
        self.extract_import_statements(root.as_ref(), tree, &mut nodes).await?;

        Ok(nodes)
    }

    async fn extract_edges(&self, tree: &dyn SyntaxTree, nodes: &[&dyn CodeNode]) -> Result<Vec<Box<dyn CodeEdge>>> {
        let mut edges = Vec::new();

        // Create a map for quick node lookup
        let node_map: HashMap<String, &dyn CodeNode> = nodes
            .iter()
            .map(|node| (node.name().to_string(), *node))
            .collect();

        // Extract function calls
        self.extract_function_calls(tree, &node_map, &mut edges).await?;

        // Extract class inheritance
        self.extract_class_inheritance(tree, &node_map, &mut edges).await?;

        // Extract variable references
        self.extract_variable_references(tree, &node_map, &mut edges).await?;

        Ok(edges)
    }

    fn map_syntax_type_to_node_type(&self, syntax_type: &str) -> NodeType {
        match syntax_type {
            "function_definition" => NodeType::Function,
            "class_definition" => NodeType::Class,
            "assignment" => NodeType::Variable,
            "import_statement" | "import_from_statement" => NodeType::Import,
            "call" => NodeType::Call,
            "identifier" => NodeType::Reference,
            _ => NodeType::Unknown,
        }
    }
}

impl PythonAdapter {
    async fn extract_function_definitions(
        &self,
        _root: &dyn codegraph_core::SyntaxNode,
        tree: &dyn SyntaxTree,
        nodes: &mut Vec<Box<dyn CodeNode>>,
    ) -> Result<()> {
        // Enhanced query to capture more function details
        let query_str = r#"
            (function_definition
                name: (identifier) @func_name
                parameters: (parameters) @params
                body: (block) @body
                return_type: (type)? @return_type) @function
        "#;

        // Also capture decorators and docstrings
        let decorator_query = r#"
            (decorated_definition
                (decorator_list) @decorators
                definition: (function_definition
                    name: (identifier) @func_name
                    parameters: (parameters) @params
                    body: (block) @body)) @decorated_function
        "#;

        if let Ok(parser) = codegraph_parser::TreeSitterParser::python() {
            // Process regular function definitions
            if let Ok(matches) = parser.query(query_str, tree) {
                for query_match in matches {
                    if let Some(func_node) = query_match.captures.get("func_name") {
                        let func_name = func_node.text().trim();
                        let start_pos = func_node.start_position();
                        let end_pos = func_node.end_position();

                        // Extract parameters
                        let parameters = if let Some(params_node) = query_match.captures.get("params") {
                            self.extract_function_parameters(params_node.as_ref())
                        } else {
                            Vec::new()
                        };

                        // Extract return type
                        let return_type = query_match.captures.get("return_type")
                            .map(|rt| rt.text().trim().to_string());

                        // Extract docstring from function body
                        let documentation = if let Some(body_node) = query_match.captures.get("body") {
                            self.extract_docstring(body_node.as_ref())
                        } else {
                            None
                        };

                        // Calculate complexity metrics
                        let complexity = if let Some(body_node) = query_match.captures.get("body") {
                            self.calculate_function_complexity(body_node.as_ref())
                        } else {
                            codegraph_graph::ComplexityMetrics::default()
                        };

                        // Create semantic info
                        let parameter_count = parameters.len();
                        let semantic_info = codegraph_graph::SemanticInfo {
                            documentation,
                            visibility: Some(self.determine_visibility(func_name)),
                            modifiers: Vec::new(), // Will be filled by decorator analysis
                            type_signature: Some(self.build_function_signature(func_name, &parameters, return_type.as_deref())),
                            parameters,
                            return_type,
                            complexity,
                        };

                        let mut node = GraphNode::with_semantic_info(
                            Uuid::new_v4(),
                            NodeType::Function,
                            func_name.to_string(),
                            SourceLocation::new(
                                "python_file.py".to_string(), // TODO: Get actual file path
                                start_pos.row,
                                start_pos.column,
                                end_pos.row,
                                end_pos.column,
                            ),
                            "python".to_string(),
                            semantic_info,
                        );

                        // Add function-specific attributes
                        node.set_attribute("is_async".to_string(), "false".to_string());
                        node.set_attribute("parameter_count".to_string(), parameter_count.to_string());

                        nodes.push(Box::new(node));
                    }
                }
            }

            // Process decorated functions
            if let Ok(matches) = parser.query(decorator_query, tree) {
                for query_match in matches {
                    if let Some(func_node) = query_match.captures.get("func_name") {
                        let func_name = func_node.text().trim();

                        // Extract decorators
                        let decorators = if let Some(decorators_node) = query_match.captures.get("decorators") {
                            self.extract_decorators(decorators_node.as_ref())
                        } else {
                            Vec::new()
                        };

                        // Find the corresponding function node and update it
                        if let Some(existing_node) = nodes.iter_mut()
                            .find(|n| n.name() == func_name && matches!(n.node_type(), NodeType::Function)) {

                            // Update modifiers with decorators
                            if let Some(node) = existing_node.as_any_mut().downcast_mut::<GraphNode>() {
                                for decorator in decorators {
                                    node.set_attribute(format!("decorator_{}", decorator), "true".to_string());
                                }
                            }
                        }
                    }
                }
            }
        }

        Ok(())
    }

    async fn extract_class_definitions(
        &self,
        _root: &dyn codegraph_core::SyntaxNode,
        tree: &dyn SyntaxTree,
        nodes: &mut Vec<Box<dyn CodeNode>>,
    ) -> Result<()> {
        // Enhanced query to capture class details including decorators
        let query_str = r#"
            (class_definition
                name: (identifier) @class_name
                superclasses: (argument_list)? @superclasses
                body: (block) @body) @class
        "#;

        let decorated_class_query = r#"
            (decorated_definition
                (decorator_list) @decorators
                definition: (class_definition
                    name: (identifier) @class_name
                    superclasses: (argument_list)? @superclasses
                    body: (block) @body)) @decorated_class
        "#;

        if let Ok(parser) = codegraph_parser::TreeSitterParser::python() {
            // Process regular class definitions
            if let Ok(matches) = parser.query(query_str, tree) {
                for query_match in matches {
                    if let Some(class_node) = query_match.captures.get("class_name") {
                        let class_name = class_node.text().trim();
                        let start_pos = class_node.start_position();
                        let end_pos = class_node.end_position();

                        // Extract superclasses
                        let superclasses = if let Some(superclasses_node) = query_match.captures.get("superclasses") {
                            self.extract_superclasses(superclasses_node.as_ref())
                        } else {
                            Vec::new()
                        };

                        // Extract class docstring
                        let documentation = if let Some(body_node) = query_match.captures.get("body") {
                            self.extract_docstring(body_node.as_ref())
                        } else {
                            None
                        };

                        // Analyze class methods and attributes
                        let (method_count, attribute_count) = if let Some(body_node) = query_match.captures.get("body") {
                            self.analyze_class_members(body_node.as_ref())
                        } else {
                            (0, 0)
                        };

                        // Calculate class complexity
                        let complexity = if let Some(body_node) = query_match.captures.get("body") {
                            self.calculate_class_complexity(body_node.as_ref())
                        } else {
                            codegraph_graph::ComplexityMetrics::default()
                        };

                        // Create semantic info
                        let semantic_info = codegraph_graph::SemanticInfo {
                            documentation,
                            visibility: Some(self.determine_visibility(class_name)),
                            modifiers: Vec::new(), // Will be filled by decorator analysis
                            type_signature: Some(format!("class {}", class_name)),
                            parameters: Vec::new(), // Classes don't have parameters
                            return_type: None,
                            complexity,
                        };

                        let mut node = GraphNode::with_semantic_info(
                            Uuid::new_v4(),
                            NodeType::Class,
                            class_name.to_string(),
                            SourceLocation::new(
                                "python_file.py".to_string(), // TODO: Get actual file path
                                start_pos.row,
                                start_pos.column,
                                end_pos.row,
                                end_pos.column,
                            ),
                            "python".to_string(),
                            semantic_info,
                        );

                        // Add class-specific attributes
                        node.set_attribute("superclasses".to_string(), superclasses.join(", "));
                        node.set_attribute("method_count".to_string(), method_count.to_string());
                        node.set_attribute("attribute_count".to_string(), attribute_count.to_string());
                        node.set_attribute("is_abstract".to_string(),
                            if superclasses.iter().any(|s| s.contains("ABC") || s.contains("Abstract")) {
                                "true"
                            } else {
                                "false"
                            }.to_string());

                        nodes.push(Box::new(node));
                    }
                }
            }

            // Process decorated classes
            if let Ok(matches) = parser.query(decorated_class_query, tree) {
                for query_match in matches {
                    if let Some(class_node) = query_match.captures.get("class_name") {
                        let class_name = class_node.text().trim();

                        // Extract decorators
                        let decorators = if let Some(decorators_node) = query_match.captures.get("decorators") {
                            self.extract_decorators(decorators_node.as_ref())
                        } else {
                            Vec::new()
                        };

                        // Find the corresponding class node and update it
                        if let Some(existing_node) = nodes.iter_mut()
                            .find(|n| n.name() == class_name && matches!(n.node_type(), NodeType::Class)) {

                            // Update modifiers with decorators
                            if let Some(node) = existing_node.as_any_mut().downcast_mut::<GraphNode>() {
                                for decorator in decorators {
                                    node.set_attribute(format!("decorator_{}", decorator), "true".to_string());
                                }
                            }
                        }
                    }
                }
            }
        }

        Ok(())
    }

    async fn extract_variable_assignments(
        &self,
        _root: &dyn codegraph_core::SyntaxNode,
        tree: &dyn SyntaxTree,
        nodes: &mut Vec<Box<dyn CodeNode>>,
    ) -> Result<()> {
        // Enhanced queries for different types of variable assignments
        let assignment_query = r#"
            (assignment
                left: (identifier) @var_name
                right: (_) @value
                type: (type)? @var_type) @assignment
        "#;

        let annotated_assignment_query = r#"
            (annotated_assignment
                annotation: (type) @var_type
                target: (identifier) @var_name
                value: (_)? @value) @annotated_assignment
        "#;

        if let Ok(parser) = codegraph_parser::TreeSitterParser::python() {
            // Process regular assignments
            if let Ok(matches) = parser.query(assignment_query, tree) {
                for query_match in matches {
                    if let Some(var_node) = query_match.captures.get("var_name") {
                        let var_name = var_node.text().trim();
                        let start_pos = var_node.start_position();
                        let end_pos = var_node.end_position();

                        // Extract value information
                        let value_info = if let Some(value_node) = query_match.captures.get("value") {
                            self.analyze_variable_value(value_node.as_ref())
                        } else {
                            ("unknown".to_string(), None)
                        };

                        // Create semantic info
                        let return_type = value_info.1.clone();
                        let semantic_info = codegraph_graph::SemanticInfo {
                            documentation: None,
                            visibility: Some(self.determine_visibility(var_name)),
                            modifiers: Vec::new(),
                            type_signature: Some(format!("{}: {}", var_name, value_info.0)),
                            parameters: Vec::new(),
                            return_type,
                            complexity: codegraph_graph::ComplexityMetrics::default(),
                        };

                        let mut node = GraphNode::with_semantic_info(
                            Uuid::new_v4(),
                            NodeType::Variable,
                            var_name.to_string(),
                            SourceLocation::new(
                                "python_file.py".to_string(), // TODO: Get actual file path
                                start_pos.row,
                                start_pos.column,
                                end_pos.row,
                                end_pos.column,
                            ),
                            "python".to_string(),
                            semantic_info,
                        );

                        // Add variable-specific attributes
                        node.set_attribute("value_type".to_string(), value_info.0);
                        if let Some(inferred_type) = value_info.1 {
                            node.set_attribute("inferred_type".to_string(), inferred_type);
                        }

                        nodes.push(Box::new(node));
                    }
                }
            }

            // Process annotated assignments (with type hints)
            if let Ok(matches) = parser.query(annotated_assignment_query, tree) {
                for query_match in matches {
                    if let Some(var_node) = query_match.captures.get("var_name") {
                        let var_name = var_node.text().trim();
                        let start_pos = var_node.start_position();
                        let end_pos = var_node.end_position();

                        // Extract type annotation
                        let type_annotation = query_match.captures.get("var_type")
                            .map(|t| t.text().trim().to_string())
                            .unwrap_or_else(|| "Any".to_string());

                        // Extract value information
                        let value_info = if let Some(value_node) = query_match.captures.get("value") {
                            self.analyze_variable_value(value_node.as_ref())
                        } else {
                            ("uninitialized".to_string(), None)
                        };

                        // Create semantic info
                        let semantic_info = codegraph_graph::SemanticInfo {
                            documentation: None,
                            visibility: Some(self.determine_visibility(var_name)),
                            modifiers: Vec::new(),
                            type_signature: Some(format!("{}: {}", var_name, type_annotation)),
                            parameters: Vec::new(),
                            return_type: Some(type_annotation.clone()),
                            complexity: codegraph_graph::ComplexityMetrics::default(),
                        };

                        let mut node = GraphNode::with_semantic_info(
                            Uuid::new_v4(),
                            NodeType::Variable,
                            var_name.to_string(),
                            SourceLocation::new(
                                "python_file.py".to_string(), // TODO: Get actual file path
                                start_pos.row,
                                start_pos.column,
                                end_pos.row,
                                end_pos.column,
                            ),
                            "python".to_string(),
                            semantic_info,
                        );

                        // Add variable-specific attributes
                        node.set_attribute("declared_type".to_string(), type_annotation);
                        node.set_attribute("value_type".to_string(), value_info.0);
                        node.set_attribute("has_type_annotation".to_string(), "true".to_string());

                        nodes.push(Box::new(node));
                    }
                }
            }
        }

        Ok(())
    }

    async fn extract_import_statements(
        &self,
        _root: &dyn codegraph_core::SyntaxNode,
        tree: &dyn SyntaxTree,
        nodes: &mut Vec<Box<dyn CodeNode>>,
    ) -> Result<()> {
        // Enhanced queries for different import types
        let import_query = r#"
            (import_statement
                name: (dotted_name) @import_name) @import
        "#;

        let from_import_query = r#"
            (import_from_statement
                module_name: (dotted_name) @module_name
                name: (import_list) @import_list) @from_import
        "#;

        let aliased_import_query = r#"
            (import_statement
                name: (aliased_import
                    name: (dotted_name) @import_name
                    alias: (identifier) @alias)) @aliased_import
        "#;

        if let Ok(parser) = codegraph_parser::TreeSitterParser::python() {
            // Handle regular import statements
            if let Ok(matches) = parser.query(import_query, tree) {
                for query_match in matches {
                    if let Some(import_node) = query_match.captures.get("import_name") {
                        let import_name = import_node.text().trim();
                        let start_pos = import_node.start_position();
                        let end_pos = import_node.end_position();

                        // Analyze import characteristics
                        let (import_type, is_standard_library) = self.analyze_import(import_name);

                        // Create semantic info
                        let semantic_info = codegraph_graph::SemanticInfo {
                            documentation: Some(format!("Import of module: {}", import_name)),
                            visibility: Some("public".to_string()),
                            modifiers: vec![import_type.clone()],
                            type_signature: Some(format!("import {}", import_name)),
                            parameters: Vec::new(),
                            return_type: Some("module".to_string()),
                            complexity: codegraph_graph::ComplexityMetrics::default(),
                        };

                        let mut node = GraphNode::with_semantic_info(
                            Uuid::new_v4(),
                            NodeType::Import,
                            import_name.to_string(),
                            SourceLocation::new(
                                "python_file.py".to_string(), // TODO: Get actual file path
                                start_pos.row,
                                start_pos.column,
                                end_pos.row,
                                end_pos.column,
                            ),
                            "python".to_string(),
                            semantic_info,
                        );

                        // Add import-specific attributes
                        node.set_attribute("import_type".to_string(), import_type);
                        node.set_attribute("is_standard_library".to_string(), is_standard_library.to_string());
                        node.set_attribute("import_style".to_string(), "direct".to_string());

                        nodes.push(Box::new(node));
                    }
                }
            }

            // Handle from...import statements
            if let Ok(matches) = parser.query(from_import_query, tree) {
                for query_match in matches {
                    if let Some(module_node) = query_match.captures.get("module_name") {
                        let module_name = module_node.text().trim();
                        let start_pos = module_node.start_position();
                        let end_pos = module_node.end_position();

                        // Extract imported items
                        let imported_items = if let Some(import_list_node) = query_match.captures.get("import_list") {
                            self.extract_import_list(import_list_node.as_ref())
                        } else {
                            Vec::new()
                        };

                        // Analyze import characteristics
                        let (import_type, is_standard_library) = self.analyze_import(module_name);

                        // Create semantic info
                        let semantic_info = codegraph_graph::SemanticInfo {
                            documentation: Some(format!("From import: {} from {}",
                                imported_items.join(", "), module_name)),
                            visibility: Some("public".to_string()),
                            modifiers: vec![import_type.clone()],
                            type_signature: Some(format!("from {} import {}",
                                module_name, imported_items.join(", "))),
                            parameters: Vec::new(),
                            return_type: Some("symbols".to_string()),
                            complexity: codegraph_graph::ComplexityMetrics::default(),
                        };

                        let mut node = GraphNode::with_semantic_info(
                            Uuid::new_v4(),
                            NodeType::Import,
                            format!("from {}", module_name),
                            SourceLocation::new(
                                "python_file.py".to_string(), // TODO: Get actual file path
                                start_pos.row,
                                start_pos.column,
                                end_pos.row,
                                end_pos.column,
                            ),
                            "python".to_string(),
                            semantic_info,
                        );

                        // Add import-specific attributes
                        node.set_attribute("import_type".to_string(), import_type);
                        node.set_attribute("is_standard_library".to_string(), is_standard_library.to_string());
                        node.set_attribute("import_style".to_string(), "from_import".to_string());
                        node.set_attribute("imported_items".to_string(), imported_items.join(", "));
                        node.set_attribute("item_count".to_string(), imported_items.len().to_string());

                        nodes.push(Box::new(node));
                    }
                }
            }

            // Handle aliased imports
            if let Ok(matches) = parser.query(aliased_import_query, tree) {
                for query_match in matches {
                    if let (Some(import_node), Some(alias_node)) = (
                        query_match.captures.get("import_name"),
                        query_match.captures.get("alias")
                    ) {
                        let import_name = import_node.text().trim();
                        let alias_name = alias_node.text().trim();
                        let start_pos = import_node.start_position();
                        let end_pos = alias_node.end_position();

                        // Analyze import characteristics
                        let (import_type, is_standard_library) = self.analyze_import(import_name);

                        // Create semantic info
                        let semantic_info = codegraph_graph::SemanticInfo {
                            documentation: Some(format!("Aliased import: {} as {}", import_name, alias_name)),
                            visibility: Some("public".to_string()),
                            modifiers: vec![import_type.clone(), "aliased".to_string()],
                            type_signature: Some(format!("import {} as {}", import_name, alias_name)),
                            parameters: Vec::new(),
                            return_type: Some("module".to_string()),
                            complexity: codegraph_graph::ComplexityMetrics::default(),
                        };

                        let mut node = GraphNode::with_semantic_info(
                            Uuid::new_v4(),
                            NodeType::Import,
                            format!("{} as {}", import_name, alias_name),
                            SourceLocation::new(
                                "python_file.py".to_string(), // TODO: Get actual file path
                                start_pos.row,
                                start_pos.column,
                                end_pos.row,
                                end_pos.column,
                            ),
                            "python".to_string(),
                            semantic_info,
                        );

                        // Add import-specific attributes
                        node.set_attribute("import_type".to_string(), import_type);
                        node.set_attribute("is_standard_library".to_string(), is_standard_library.to_string());
                        node.set_attribute("import_style".to_string(), "aliased".to_string());
                        node.set_attribute("original_name".to_string(), import_name.to_string());
                        node.set_attribute("alias_name".to_string(), alias_name.to_string());

                        nodes.push(Box::new(node));
                    }
                }
            }
        }

        Ok(())
    }

    async fn extract_function_calls(
        &self,
        tree: &dyn SyntaxTree,
        node_map: &HashMap<String, &dyn CodeNode>,
        edges: &mut Vec<Box<dyn CodeEdge>>,
    ) -> Result<()> {
        // Use Tree-sitter query to find function calls
        let call_query = r#"
            (call
                function: (identifier) @func_name
                arguments: (argument_list) @args) @call
        "#;

        if let Ok(parser) = codegraph_parser::TreeSitterParser::python() {
            if let Ok(matches) = parser.query(call_query, tree) {
                for query_match in matches {
                    if let Some(func_node) = query_match.captures.get("func_name") {
                        let func_name = func_node.text().trim();

                        // Find the called function in our node map
                        if let Some(target_node) = node_map.get(func_name) {
                            // Find a caller node (simplified: use any function node as caller)
                            for (node_name, source_node) in node_map {
                                if node_name != func_name &&
                                   matches!(source_node.node_type(), NodeType::Function) {
                                    let edge = GraphEdge::new(
                                        Uuid::new_v4(),
                                        source_node.id(),
                                        target_node.id(),
                                        EdgeType::Calls,
                                    );
                                    edges.push(Box::new(edge));
                                    break; // Only create one edge per call for now
                                }
                            }
                        }
                    }
                }
            }
        }

        Ok(())
    }

    async fn extract_class_inheritance(
        &self,
        tree: &dyn SyntaxTree,
        node_map: &HashMap<String, &dyn CodeNode>,
        edges: &mut Vec<Box<dyn CodeEdge>>,
    ) -> Result<()> {
        // Use Tree-sitter query to find class inheritance
        let inheritance_query = r#"
            (class_definition
                name: (identifier) @class_name
                superclasses: (argument_list
                    (identifier) @parent_class)) @class
        "#;

        if let Ok(parser) = codegraph_parser::TreeSitterParser::python() {
            if let Ok(matches) = parser.query(inheritance_query, tree) {
                for query_match in matches {
                    if let (Some(class_node), Some(parent_node)) = (
                        query_match.captures.get("class_name"),
                        query_match.captures.get("parent_class")
                    ) {
                        let class_name = class_node.text().trim();
                        let parent_name = parent_node.text().trim();

                        // Find both classes in our node map
                        if let (Some(child_node), Some(parent_node)) = (
                            node_map.get(class_name),
                            node_map.get(parent_name)
                        ) {
                            let edge = GraphEdge::new(
                                Uuid::new_v4(),
                                child_node.id(),
                                parent_node.id(),
                                EdgeType::Inherits,
                            );
                            edges.push(Box::new(edge));
                        }
                    }
                }
            }
        }

        Ok(())
    }

    async fn extract_variable_references(
        &self,
        tree: &dyn SyntaxTree,
        node_map: &HashMap<String, &dyn CodeNode>,
        edges: &mut Vec<Box<dyn CodeEdge>>,
    ) -> Result<()> {
        // Use Tree-sitter query to find variable references
        let reference_query = r#"
            (identifier) @var_ref
        "#;

        if let Ok(parser) = codegraph_parser::TreeSitterParser::python() {
            if let Ok(matches) = parser.query(reference_query, tree) {
                for query_match in matches {
                    if let Some(ref_node) = query_match.captures.get("var_ref") {
                        let var_name = ref_node.text().trim();

                        // Find the referenced variable in our node map
                        if let Some(target_node) = node_map.get(var_name) {
                            // Find a referencing context (simplified: use any function as context)
                            for (node_name, source_node) in node_map {
                                if node_name != var_name &&
                                   matches!(source_node.node_type(), NodeType::Function) {
                                    let edge = GraphEdge::new(
                                        Uuid::new_v4(),
                                        source_node.id(),
                                        target_node.id(),
                                        EdgeType::References,
                                    );
                                    edges.push(Box::new(edge));
                                    break; // Only create one edge per reference for now
                                }
                            }
                        }
                    }
                }
            }
        }

        Ok(())
    }

    /// Extract function parameters with type information
    fn extract_function_parameters(&self, params_node: &dyn codegraph_core::SyntaxNode) -> Vec<codegraph_graph::Parameter> {
        let mut parameters = Vec::new();

        // Simple parameter extraction - in a real implementation, you'd parse the parameter list
        let params_text = params_node.text();
        if !params_text.trim().is_empty() && params_text != "()" {
            // Split by comma and parse each parameter
            let param_parts: Vec<&str> = params_text.trim_matches(|c| c == '(' || c == ')').split(',').collect();

            for param_part in param_parts {
                let param_part = param_part.trim();
                if !param_part.is_empty() && param_part != "self" {
                    let (name, param_type, default_value, is_optional) = self.parse_parameter(param_part);

                    parameters.push(codegraph_graph::Parameter {
                        name,
                        param_type,
                        default_value,
                        is_optional,
                    });
                }
            }
        }

        parameters
    }

    /// Parse individual parameter with type hints and default values
    fn parse_parameter(&self, param_str: &str) -> (String, Option<String>, Option<String>, bool) {
        let param_str = param_str.trim();

        // Handle default values
        let (param_part, default_value) = if param_str.contains('=') {
            let parts: Vec<&str> = param_str.splitn(2, '=').collect();
            (parts[0].trim(), Some(parts[1].trim().to_string()))
        } else {
            (param_str, None)
        };

        // Handle type annotations
        let (name, param_type) = if param_part.contains(':') {
            let parts: Vec<&str> = param_part.splitn(2, ':').collect();
            (parts[0].trim().to_string(), Some(parts[1].trim().to_string()))
        } else {
            (param_part.to_string(), None)
        };

        let is_optional = default_value.is_some() ||
                         param_type.as_ref().map_or(false, |t| t.contains("Optional") || t.contains("None"));

        (name, param_type, default_value, is_optional)
    }

    /// Extract docstring from function body
    fn extract_docstring(&self, body_node: &dyn codegraph_core::SyntaxNode) -> Option<String> {
        let body_text = body_node.text();

        // Look for docstring patterns
        if let Some(start) = body_text.find("\"\"\"") {
            if let Some(end) = body_text[start + 3..].find("\"\"\"") {
                let docstring = &body_text[start + 3..start + 3 + end];
                return Some(docstring.trim().to_string());
            }
        }

        if let Some(start) = body_text.find("'''") {
            if let Some(end) = body_text[start + 3..].find("'''") {
                let docstring = &body_text[start + 3..start + 3 + end];
                return Some(docstring.trim().to_string());
            }
        }

        None
    }

    /// Calculate function complexity metrics
    fn calculate_function_complexity(&self, body_node: &dyn codegraph_core::SyntaxNode) -> codegraph_graph::ComplexityMetrics {
        let body_text = body_node.text();
        let lines: Vec<&str> = body_text.lines().collect();

        // Simple complexity calculation
        let mut cyclomatic = 1; // Base complexity
        let mut cognitive = 0;
        let mut nesting_depth = 0;
        let mut current_depth = 0;

        for line in &lines {
            let trimmed = line.trim();

            // Count decision points for cyclomatic complexity
            if trimmed.starts_with("if ") || trimmed.contains(" if ") {
                cyclomatic += 1;
                cognitive += 1 + current_depth;
            }
            if trimmed.starts_with("elif ") {
                cyclomatic += 1;
                cognitive += 1 + current_depth;
            }
            if trimmed.starts_with("for ") || trimmed.starts_with("while ") {
                cyclomatic += 1;
                cognitive += 1 + current_depth;
            }
            if trimmed.starts_with("except ") || trimmed.contains("except ") {
                cyclomatic += 1;
                cognitive += 1 + current_depth;
            }
            if trimmed.contains(" and ") || trimmed.contains(" or ") {
                cyclomatic += 1;
            }

            // Track nesting depth
            if trimmed.ends_with(':') && (
                trimmed.starts_with("if ") || trimmed.starts_with("elif ") ||
                trimmed.starts_with("else:") || trimmed.starts_with("for ") ||
                trimmed.starts_with("while ") || trimmed.starts_with("try:") ||
                trimmed.starts_with("except ") || trimmed.starts_with("finally:")
            ) {
                current_depth += 1;
                nesting_depth = nesting_depth.max(current_depth);
            }

            // Decrease depth (simplified - just look for dedentation)
            if !trimmed.is_empty() && !line.starts_with(' ') && current_depth > 0 {
                current_depth = 0;
            }
        }

        codegraph_graph::ComplexityMetrics {
            cyclomatic: cyclomatic as u32,
            cognitive: cognitive as u32,
            lines_of_code: lines.len() as u32,
            parameter_count: 0, // Will be set separately
            nesting_depth: nesting_depth as u32,
        }
    }

    /// Determine function visibility
    fn determine_visibility(&self, func_name: &str) -> String {
        if func_name.starts_with("__") && func_name.ends_with("__") {
            "magic".to_string()
        } else if func_name.starts_with("__") {
            "private".to_string()
        } else if func_name.starts_with('_') {
            "protected".to_string()
        } else {
            "public".to_string()
        }
    }

    /// Build function signature string
    fn build_function_signature(&self, name: &str, parameters: &[codegraph_graph::Parameter], return_type: Option<&str>) -> String {
        let param_strs: Vec<String> = parameters.iter().map(|p| {
            let mut param_str = p.name.clone();
            if let Some(ref param_type) = p.param_type {
                param_str.push_str(&format!(": {}", param_type));
            }
            if let Some(ref default) = p.default_value {
                param_str.push_str(&format!(" = {}", default));
            }
            param_str
        }).collect();

        let params_str = param_strs.join(", ");
        let return_str = return_type.map_or(String::new(), |rt| format!(" -> {}", rt));

        format!("{}({}){}", name, params_str, return_str)
    }

    /// Extract decorators from decorator list
    fn extract_decorators(&self, decorators_node: &dyn codegraph_core::SyntaxNode) -> Vec<String> {
        let decorators_text = decorators_node.text();
        let mut decorators = Vec::new();

        // Simple decorator extraction
        for line in decorators_text.lines() {
            let trimmed = line.trim();
            if trimmed.starts_with('@') {
                let decorator = trimmed[1..].trim();
                // Remove parentheses if present
                let decorator = if decorator.contains('(') {
                    decorator.split('(').next().unwrap_or(decorator)
                } else {
                    decorator
                };
                decorators.push(decorator.to_string());
            }
        }

        decorators
    }

    /// Extract superclasses from argument list
    fn extract_superclasses(&self, superclasses_node: &dyn codegraph_core::SyntaxNode) -> Vec<String> {
        let superclasses_text = superclasses_node.text();
        let mut superclasses = Vec::new();

        // Remove parentheses and split by comma
        let cleaned = superclasses_text.trim_matches(|c| c == '(' || c == ')');
        if !cleaned.is_empty() {
            for superclass in cleaned.split(',') {
                let superclass = superclass.trim();
                if !superclass.is_empty() {
                    superclasses.push(superclass.to_string());
                }
            }
        }

        superclasses
    }

    /// Analyze class members (methods and attributes)
    fn analyze_class_members(&self, body_node: &dyn codegraph_core::SyntaxNode) -> (usize, usize) {
        let body_text = body_node.text();
        let mut method_count = 0;
        let mut attribute_count = 0;

        for line in body_text.lines() {
            let trimmed = line.trim();

            // Count method definitions
            if trimmed.starts_with("def ") {
                method_count += 1;
            }

            // Count attribute assignments (simplified)
            if trimmed.starts_with("self.") && trimmed.contains(" = ") {
                attribute_count += 1;
            }
        }

        (method_count, attribute_count)
    }

    /// Calculate class complexity metrics
    fn calculate_class_complexity(&self, body_node: &dyn codegraph_core::SyntaxNode) -> codegraph_graph::ComplexityMetrics {
        let body_text = body_node.text();
        let lines: Vec<&str> = body_text.lines().collect();

        let mut cyclomatic = 1; // Base complexity
        let mut cognitive = 0;
        let mut nesting_depth = 0;
        let mut current_depth = 0;
        let mut method_count = 0;

        for line in &lines {
            let trimmed = line.trim();

            // Count methods
            if trimmed.starts_with("def ") {
                method_count += 1;
                cyclomatic += 1; // Each method adds complexity
            }

            // Count decision points
            if trimmed.starts_with("if ") || trimmed.contains(" if ") {
                cyclomatic += 1;
                cognitive += 1 + current_depth;
            }
            if trimmed.starts_with("elif ") {
                cyclomatic += 1;
                cognitive += 1 + current_depth;
            }
            if trimmed.starts_with("for ") || trimmed.starts_with("while ") {
                cyclomatic += 1;
                cognitive += 1 + current_depth;
            }
            if trimmed.starts_with("except ") || trimmed.contains("except ") {
                cyclomatic += 1;
                cognitive += 1 + current_depth;
            }

            // Track nesting depth
            if trimmed.ends_with(':') {
                current_depth += 1;
                nesting_depth = nesting_depth.max(current_depth);
            }

            // Simplified depth tracking
            if !trimmed.is_empty() && !line.starts_with(' ') && current_depth > 0 {
                current_depth = 0;
            }
        }

        codegraph_graph::ComplexityMetrics {
            cyclomatic: cyclomatic as u32,
            cognitive: cognitive as u32,
            lines_of_code: lines.len() as u32,
            parameter_count: method_count as u32,
            nesting_depth: nesting_depth as u32,
        }
    }

    /// Analyze variable value to infer type and characteristics
    fn analyze_variable_value(&self, value_node: &dyn codegraph_core::SyntaxNode) -> (String, Option<String>) {
        let value_text = value_node.text().trim();

        // Infer type from value
        let (value_type, inferred_type) = if value_text.starts_with('"') || value_text.starts_with('\'') {
            ("string_literal".to_string(), Some("str".to_string()))
        } else if value_text.parse::<i64>().is_ok() {
            ("integer_literal".to_string(), Some("int".to_string()))
        } else if value_text.parse::<f64>().is_ok() {
            ("float_literal".to_string(), Some("float".to_string()))
        } else if value_text == "True" || value_text == "False" {
            ("boolean_literal".to_string(), Some("bool".to_string()))
        } else if value_text == "None" {
            ("none_literal".to_string(), Some("None".to_string()))
        } else if value_text.starts_with('[') && value_text.ends_with(']') {
            ("list_literal".to_string(), Some("list".to_string()))
        } else if value_text.starts_with('{') && value_text.ends_with('}') {
            if value_text.contains(':') {
                ("dict_literal".to_string(), Some("dict".to_string()))
            } else {
                ("set_literal".to_string(), Some("set".to_string()))
            }
        } else if value_text.starts_with('(') && value_text.ends_with(')') {
            ("tuple_literal".to_string(), Some("tuple".to_string()))
        } else if value_text.contains('(') && value_text.contains(')') {
            ("function_call".to_string(), None) // Type depends on function return
        } else {
            ("identifier".to_string(), None) // Type depends on referenced variable
        };

        (value_type, inferred_type)
    }

    /// Analyze import to determine type and characteristics
    fn analyze_import(&self, import_name: &str) -> (String, bool) {
        // Standard library modules (partial list)
        let standard_library = [
            "os", "sys", "re", "json", "datetime", "collections", "itertools",
            "functools", "operator", "pathlib", "urllib", "http", "email",
            "xml", "html", "sqlite3", "csv", "configparser", "logging",
            "unittest", "doctest", "pdb", "profile", "timeit", "trace",
            "math", "random", "statistics", "decimal", "fractions",
            "string", "textwrap", "unicodedata", "stringprep", "readline",
            "rlcompleter", "struct", "codecs", "types", "copy", "pprint",
            "reprlib", "enum", "numbers", "cmath", "decimal", "fractions",
        ];

        let is_standard_library = standard_library.iter().any(|&stdlib| {
            import_name == stdlib || import_name.starts_with(&format!("{}.", stdlib))
        });

        let import_type = if is_standard_library {
            "standard_library".to_string()
        } else if import_name.starts_with('.') {
            "relative_import".to_string()
        } else if import_name.contains('.') {
            "package_import".to_string()
        } else {
            "module_import".to_string()
        };

        (import_type, is_standard_library)
    }

    /// Extract items from import list
    fn extract_import_list(&self, import_list_node: &dyn codegraph_core::SyntaxNode) -> Vec<String> {
        let import_list_text = import_list_node.text();
        let mut items = Vec::new();

        // Simple parsing of import list
        for item in import_list_text.split(',') {
            let item = item.trim();
            if !item.is_empty() {
                // Handle aliased imports in the list
                if item.contains(" as ") {
                    let parts: Vec<&str> = item.split(" as ").collect();
                    if parts.len() == 2 {
                        items.push(format!("{} as {}", parts[0].trim(), parts[1].trim()));
                    } else {
                        items.push(item.to_string());
                    }
                } else {
                    items.push(item.to_string());
                }
            }
        }

        items
    }
}
